#pragma once
#include <iostream>
#include <queue>
#include <pthread.h>
#include "Log.hpp"
#include "Task.hpp"

#define MAX_NUM 10

class ThreadPool
{
    private:
    int num_;
    bool stop_;
    std::queue<Task> task_queue_;
    pthread_mutex_t lock_;
    pthread_cond_t cond_;
    ThreadPool(int num=MAX_NUM)
    :num_(num),stop_(false)
    {
        pthread_mutex_init(&lock_,nullptr);
        pthread_cond_init(&cond_,nullptr);
    }
    ThreadPool(const ThreadPool& ) =delete;

    static ThreadPool* sigle_instance;
    
    public:
    static void* Thread_Routine(void* args)
    {
        // cout<<"Thread_Routine successed"<<"3801238021"<<endl;
        ThreadPool* tp=(ThreadPool*)args;
        while(true)
        {
            Task t;
            tp->Lock();
            while(tp->Taskqueue_Is_Empty())
            {
                tp->Thread_Wait();
            }
            tp->Pop_Task(t);
            tp->UnLock();
            t.Process_On();
        }
    }
    static ThreadPool* Getinstance()
    {
        static pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
        if(sigle_instance == nullptr)
        {
            pthread_mutex_lock(&mutex);
            if(sigle_instance == nullptr)
            {
                sigle_instance=new ThreadPool();
                sigle_instance->Init_ThreadPool();
            }
            pthread_mutex_unlock(&mutex);
        }
        return sigle_instance;
    }
    bool Isstop()
    {
        return stop_;
    }
    bool Taskqueue_Is_Empty()
    {
        return task_queue_.size() == 0;
    }
    bool Lock()
    {
        pthread_mutex_lock(&lock_);
    }
    bool UnLock()
    {
        pthread_mutex_unlock(&lock_);
    }
    void Thread_Wait()
    {
        pthread_cond_wait(&cond_,&lock_);
    }
    void Thread_wake_up()
    {
        pthread_cond_signal(&cond_);
    }

    bool Init_ThreadPool()
    {
        for(int i=0;i<num_;i++)
        {
            pthread_t tid;
            if(pthread_create(&tid,nullptr,Thread_Routine,this) != 0)
            {
                LOG(FATAL,"Create ThreadPool failed");
                return false;
            }
        }
        LOG(INFO,"Create ThreadPool Successed");
        return true;
    }
    void Push_Task(Task t)
    {
        Lock();
        task_queue_.push(t);
        UnLock();
        Thread_wake_up();
    }
    void Pop_Task(Task& t)
    {
        t=task_queue_.front();
        task_queue_.pop();
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&lock_);
        pthread_cond_destroy(&cond_);
    }
};
    ThreadPool* ThreadPool::sigle_instance=nullptr;
